package com.rul.mars.user.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.github.pagehelper.PageHelper;
import com.rul.mars.common.constant.AuthConstant;
import com.rul.mars.common.service.RedisService;
import com.rul.mars.mbg.domain.ResourceParam;
import com.rul.mars.mbg.mapper.ResourceMapper;
import com.rul.mars.mbg.mapper.RoleMapper;
import com.rul.mars.mbg.mapper.RoleResourceRelationMapper;
import com.rul.mars.mbg.model.*;
import com.rul.mars.user.service.ResourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.stream.Collectors;

/**
 * 资源服务实现
 *
 * @author RuL
 */
@Service
public class ResourceServiceImpl implements ResourceService {

    @Autowired
    private ResourceMapper resourceMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RoleResourceRelationMapper roleResourceRelationMapper;

    @Autowired
    private RedisService redisService;

    @Value("${spring.application.name}")
    private String applicationName;

    /**
     * 创建新资源
     *
     * @param param 新资源参数
     * @return 操作结果
     */
    @Override
    public int create(ResourceParam param) {
        Resource resource = BeanUtil.copyProperties(param, Resource.class);
        return resourceMapper.insertSelective(resource);
    }

    /**
     * 根据资源信息
     *
     * @param resource 资源信息
     * @return 更新行数
     */
    @Override
    public int update(Resource resource) {
        int count = resourceMapper.updateByPrimaryKeySelective(resource);
        initResourceRolesMap();
        return count;
    }

    /**
     * 根据Id获取资源信息
     *
     * @param id 资源ID
     * @return 资源信息
     */
    @Override
    public Resource getItem(Long id) {
        return resourceMapper.selectByPrimaryKey(id);
    }

    /**
     * 删除资源
     *
     * @param id 资源ID
     * @return 删除数量
     */
    @Override
    public int delete(Long id) {
        int count = resourceMapper.deleteByPrimaryKey(id);
        initResourceRolesMap();
        return count;
    }

    /**
     * 分页查询资源信息
     *
     * @param nameKeyword 资源名关键字
     * @param urlKeyword  url关键字
     * @param pageSize    页面大小
     * @param pageNum     页面号
     * @return 该页资源信息
     */
    @Override
    public List<Resource> list(String nameKeyword, String urlKeyword, Integer pageSize, Integer pageNum) {
        PageHelper.startPage(pageNum, pageSize);
        ResourceExample example = new ResourceExample();
        ResourceExample.Criteria criteria = example.createCriteria();
        if (StrUtil.isNotEmpty(nameKeyword)) {
            criteria.andNameLike('%' + nameKeyword + '%');
        }
        if (StrUtil.isNotEmpty(urlKeyword)) {
            criteria.andUrlLike('%' + urlKeyword + '%');
        }
        return resourceMapper.selectByExample(example);
    }

    /**
     * 查询所有资源信息
     *
     * @return 所有资源信息
     */
    @Override
    public List<Resource> listAll() {
        return resourceMapper.selectByExample(new ResourceExample());
    }

    /**
     * 缓存中初始化资源与角色关系
     *
     * @return 资源与角色映射关系
     */
    @Override
    public Map<String, List<String>> initResourceRolesMap() {
        //存储资源与角色映射关系
        Map<String, List<String>> resourceRoleMap = new TreeMap<>();
        //所有资源
        List<Resource> resourceList = resourceMapper.selectByExample(new ResourceExample());
        //所有角色
        List<Role> roleList = roleMapper.selectByExample(new RoleExample());
        //所有角色与资源关系信息
        List<RoleResourceRelation> relationsList = roleResourceRelationMapper.selectByExample(new RoleResourceRelationExample());

        for (Resource resource : resourceList) {
            Set<Long> roleIds = relationsList.stream()
                    .filter(item -> item.getResourceId().equals(resource.getId()))
                    .map(RoleResourceRelation::getRoleId)
                    .collect(Collectors.toSet());

            List<String> roleNames = roleList.stream()
                    .filter(item -> roleIds.contains(item.getId()))
                    .map(item -> item.getId() + "_" + item.getName())
                    .collect(Collectors.toList());

            resourceRoleMap.put(resource.getUrl(), roleNames);
        }
        //删除缓存
        redisService.del(AuthConstant.RESOURCE_ROLES_MAP_KEY);
        //设置缓存
        redisService.hSetAll(AuthConstant.RESOURCE_ROLES_MAP_KEY, resourceRoleMap);
        return resourceRoleMap;
    }

}
